package com.xjrsoft.module.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.page.PageInput;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.organization.entity.*;
import com.xjrsoft.module.organization.mapper.RoleMapper;
import com.xjrsoft.module.organization.mapper.UserPostRelationMapper;
import com.xjrsoft.module.organization.mapper.UserRoleRelationMapper;
import com.xjrsoft.module.organization.vo.UserRoleVo;
import com.xjrsoft.module.system.dto.UpdateFileAuthDto;
import com.xjrsoft.module.system.entity.ExcelAuth;
import com.xjrsoft.module.system.entity.ExcelFile;
import com.xjrsoft.module.system.entity.FileAuth;
import com.xjrsoft.module.system.entity.FileManagement;
import com.xjrsoft.module.system.mapper.FileManagementMapper;
import com.xjrsoft.module.system.service.IFileAuthService;
import com.xjrsoft.module.system.service.IFileManagementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjrsoft.module.system.vo.ExcelAuthVo;
import com.xjrsoft.module.system.vo.ExcelFilePageVo;
import com.xjrsoft.module.system.vo.FileAuthVo;
import com.xjrsoft.module.system.vo.FileManagementPageVo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件管理表 服务实现类
 * </p>
 *
 * @author hnyyzy
 * @since 2024-04-07
 */
@Service
@AllArgsConstructor
public class FileManagementServiceImpl extends ServiceImpl<FileManagementMapper, FileManagement> implements IFileManagementService {

    private final UserRoleRelationMapper userRoleRelationMapper;

    private final RoleMapper roleMapper;

    private final UserPostRelationMapper userPostRelationMapper;

    private RedisUtil redisUtil;

    private final IFileAuthService fileAuthService;

    @Override
    public PageOutput<FileManagementPageVo> getPageList(PageInput dto) {
        List<FileManagement> fileManagementList = list(Wrappers.<FileManagement>lambdaQuery().like(StrUtil.isNotBlank(dto.getKeyword()), FileManagement::getFileName, dto.getKeyword()));

        //根据登录人id，查看是否有对应的excel权限
        long userId = StpUtil.getLoginIdAsLong();
        List<UserRoleRelation> relations = userRoleRelationMapper.selectList(Wrappers.lambdaQuery(UserRoleRelation.class)
                .eq(UserRoleRelation::getUserId, userId));

        List<Long> relationIds = relations.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());

        List<Role> roleList = roleMapper.selectList(Wrappers.lambdaQuery(Role.class)
                .select(Role.class, x -> VoToColumnUtil.fieldsToColumns(UserRoleVo.class).contains(x.getColumn()))
                .in(relationIds.size() > 0, Role::getId, relationIds));

        List<Long> roleIdList = roleList.stream().map(Role::getId).collect(Collectors.toList());

        //如果不是超级管理员就进行权限过滤
        if (!roleIdList.contains(GlobalConstant.SUPER_ADMIN_ROLE_ID) && fileManagementList.size() > 0) {
            //自己创建的文件，具有权限
            List<FileManagement> userCreateFile = fileManagementList.stream().filter(x -> x.getCreateUserId().equals(userId)).collect(Collectors.toList());

            //获取所有的权限数据
            List<FileAuth> fileAuthList = fileAuthService.list();

            if (fileAuthList.size() > 0) {
                //用户所具有的岗位
                List<UserPostRelation> postRelations = userPostRelationMapper.selectList(Wrappers.lambdaQuery(UserPostRelation.class).eq(UserPostRelation::getUserId, userId));

                List<Long> postIdList = postRelations.stream().map(UserPostRelation::getPostId).collect(Collectors.toList());

                //根据用户id、角色id、岗位id查询当前登录人所具有的所有excel权限
                List<Long> excelIds = fileAuthList.stream().filter(x -> x.getObjectId().equals(userId)
                        || roleIdList.contains(x.getObjectId()) || postIdList.contains(x.getObjectId())).map(FileAuth::getFileManagementId).collect(Collectors.toList());

                if (excelIds.size() > 0) {//权限过滤，一个都没有就置空
                    fileManagementList = fileManagementList.stream().filter(x -> excelIds.contains(x.getId())).collect(Collectors.toList());
                } else {
                    fileManagementList = new ArrayList<>();//置空
                }
            } else {
                fileManagementList = new ArrayList<>();//置空
            }

            //自己创建的文件，具有权限
            if (userCreateFile.size() > 0){
                fileManagementList.addAll(userCreateFile);
            }
        }

        List<FileManagementPageVo> fileManagementPageVoList = new ArrayList<>();
        if (fileManagementList.size() > 0) {
            List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
            });
            for (FileManagement fileManagement : fileManagementList) {
                FileManagementPageVo fileManagementPageVo = new FileManagementPageVo();
                fileManagementPageVo.setId(fileManagement.getId());
                fileManagementPageVo.setFileName(fileManagement.getFileName());
                fileManagementPageVo.setFileSize(fileManagement.getFileSize());
                fileManagementPageVo.setRemark(fileManagement.getRemark());
                fileManagementPageVo.setFileUrl(fileManagement.getFileUrl());
                fileManagementPageVo.setFileType(fileManagement.getFileType());
                User user = userList.stream().filter(x -> x.getId().equals(fileManagement.getCreateUserId())).findFirst().orElse(new User());
                fileManagementPageVo.setCreateUserName(user.getName());
                if (ObjectUtil.isNotEmpty(fileManagement.getModifyUserId())) {
                    fileManagementPageVo.setModifyDate(fileManagement.getModifyDate());
                } else {
                    fileManagementPageVo.setModifyDate(fileManagement.getCreateDate());
                }
                fileManagementPageVoList.add(fileManagementPageVo);
            }
        }

        PageOutput<FileManagementPageVo> output = new PageOutput<>();
        output.setCurrentPage(dto.getLimit());
        output.setPageSize(dto.getSize());
        output.setTotal(fileManagementList.size());

        if (fileManagementPageVoList.size() > 0){
            fileManagementPageVoList.sort((t1,t2)->t2.getModifyDate().compareTo(t1.getModifyDate()));
        }

        output.setList(fileManagementPageVoList);
        return output;
    }

    @Override
    public Boolean updateFileAuth(UpdateFileAuthDto dto) {
        //先全部删除
        fileAuthService.remove(Wrappers.<FileAuth>lambdaQuery().eq(FileAuth::getFileManagementId, dto.getFileManagementId()));
        //然后再新增
        if (dto.getFileAuthDtoList().size() > 0) {
            List<FileAuth> fileAuthList = BeanUtil.copyToList(dto.getFileAuthDtoList(), FileAuth.class);
            for (FileAuth fileAuth : fileAuthList) {
                fileAuth.setFileManagementId(dto.getFileManagementId());
            }
            fileAuthService.saveBatch(fileAuthList);
        }
        return true;
    }

    @Override
    public List<FileAuthVo> fileAuthInfo(Long id) {
        List<FileAuth> excelAuths = fileAuthService.list((Wrappers.<FileAuth>lambdaQuery().eq(FileAuth::getFileManagementId, id)));
        List<FileAuthVo> fileAuthVoList = new ArrayList<>();
        if (excelAuths.size() > 0) {
            for (FileAuth fileAuth : excelAuths) {
                FileAuthVo fileAuthVo = BeanUtil.toBean(fileAuth, FileAuthVo.class);
                if (fileAuth.getAuthType() == 0){
                    fileAuthVo.setAuthTypeName("用户");
                    //用户名称
                    List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
                    });
                    User user = userList.stream().filter(x -> x.getId().equals(fileAuth.getObjectId())).findFirst().orElse(new User());
                    fileAuthVo.setObjectName(user.getName());
                }else if (fileAuth.getAuthType() == 1){
                    fileAuthVo.setAuthTypeName("角色");
                    //角色名称
                    List<Role> roleList = redisUtil.get(GlobalConstant.ROLE_CACHE_KEY, new TypeReference<List<Role>>() {
                    });
                    Role role = roleList.stream().filter(x -> x.getId().equals(fileAuth.getObjectId())).findFirst().orElse(new Role());
                    fileAuthVo.setObjectName(role.getName());
                }else {
                    fileAuthVo.setAuthTypeName("岗位");
                    //岗位名称
                    List<Post> postList = redisUtil.get(GlobalConstant.POST_CACHE_KEY, new TypeReference<List<Post>>() {
                    });
                    Post post = postList.stream().filter(x -> x.getId().equals(fileAuth.getObjectId())).findFirst().orElse(new Post());
                    fileAuthVo.setObjectName(post.getName());
                }
                fileAuthVoList.add(fileAuthVo);
            }
        }
        return fileAuthVoList;
    }


}
